/* Copyright (c) 2004-2024 Peigen.info. All rights reserved. */

package info.peigen.hotpot.component.gateway.mqtt.server.service;

import com.alibaba.fastjson2.JSON;
import com.google.protobuf.Message;
import info.peigen.hotpot.component.gateway.mqtt.server.util.ProtoBufUtil;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.codec.MqttQoS;
import net.dreamlu.iot.mqtt.server.noear.MqttServerTemplate;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

/**
 * <b>(MqttServerPublishService)</b>
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2022/7/23
 */
@Slf4j
@Component
public class MqttServerPublishService {
    @Inject
    private MqttServerTemplate server;

    /**
     * 给指定的客户端发送消息
     * 至多发送一次，发送即丢弃。没有确认消息，也不知道对方是否收到。
     *
     * @param clientId 客户端Id
     * @param topic    主题
     * @param obj      需要传递的对象
     * @param builder  需要序列化的对象
     *
     * @return boolean 成功与否
     */
    public boolean publish(@NotEmpty String clientId, @NotEmpty String topic, @NotNull Object obj, @NotNull Message.Builder builder) {
        return publish(clientId, topic, obj, builder, MqttQoS.QOS0);
    }

    public boolean publish(@NotEmpty String clientId, @NotEmpty String topic, @NotEmpty String json) {
        return server.publish(clientId, topic, json.getBytes(), MqttQoS.QOS0);
    }

    /**
     * 给指定的客户端发送消息
     * 至少发送一次，发送即丢弃。没有确认消息，也不知道对方是否收到。
     *
     * @param clientId 客户端Id
     * @param topic    主题
     * @param json     需要传递的对象
     * @param builder  需要序列化的对象
     *
     * @return boolean 成功与否
     */
    @SneakyThrows
    public boolean publish(@NotEmpty String clientId, @NotEmpty String topic, @NotNull String json, @NotNull Message.Builder builder) {
        log.info("Mqtt-Server publish,ClientId:{},\nTopic:{},Obj=\n{},\nMessageFullName={}", clientId, topic, json, builder
                .getDescriptorForType().getFullName());
        boolean result = false;
        result = server.publish(clientId, topic, ProtoBufUtil.deserializationToByteArray(json, builder), MqttQoS.QOS1);
        log.info("Mqtt-Server publish result:{}", result);
        return result;
    }

    /**
     * 给指定的客户端发送消息
     *
     * @param clientId 客户端Id
     * @param topic    主题
     * @param obj      需要传递的对象
     * @param builder  需要序列化的对象
     * @param qos      服务质量
     *
     * @return boolean 成功与否
     */
    @SneakyThrows
    public boolean publish(@NotEmpty String clientId, @NotEmpty String topic, @NotNull Object obj, @NotNull Message.Builder builder, @NotNull MqttQoS qos) {
        String json = JSON.toJSONString(obj);
        log.info("Mqtt-Server publish,ClientId:{},\nTopic:{},Obj=\n{},\nMessageFullName={}", clientId, topic, json, builder
                .getDescriptorForType().getFullName());
        boolean result = false;
        result = server.publish(clientId, topic, ProtoBufUtil.deserializationToByteArray(obj, builder), qos);
        log.info("Mqtt-Server publish result:{}", result);
        return result;
    }

    /**
     * 广播
     * 至多发送一次，发送即丢弃。没有确认消息，也不知道对方是否收到。
     *
     * @param topic   主题
     * @param obj     需要传递的对象
     * @param builder 需要序列化的对象
     *
     * @return boolean 成功与否
     */
    public boolean publishAllByObject(@NotEmpty String topic, @NotNull Object obj, @NotNull Message.Builder builder) {
        return publishAll(topic, obj, builder, MqttQoS.QOS0);
    }

    /**
     * 广播
     * 至多发送一次，发送即丢弃。没有确认消息，也不知道对方是否收到。
     *
     * @param topic   主题
     * @param json    需要传递的对象
     * @param builder 需要序列化的对象
     *
     * @return boolean 成功与否
     */
    @SneakyThrows
    public boolean publishAllByJson(@NotEmpty String topic, @NotEmpty String json, @NotNull Message.Builder builder) {
        log.info("Mqtt-Server publishAll,Topic:{},\njson=\n{},\nMessageFullName={}", topic, json, builder
                .getDescriptorForType().getFullName());
        boolean result = false;
        result = server.publishAll(topic, ProtoBufUtil.deserializationToByteArray(json, builder));
        log.info("Mqtt-Server publishAll result:{}", result);
        return result;
    }

    /**
     * 广播
     *
     * @param topic   主题
     * @param obj     需要传递的对象
     * @param builder 需要序列化的对象
     * @param qos     服务质量
     *
     * @return boolean 成功与否
     */
    @SneakyThrows
    public boolean publishAll(@NotEmpty String topic, @NotNull Object obj, @NotNull Message.Builder builder, @NotNull MqttQoS qos) {
        String json = JSON.toJSONString(obj);
        log.info("Mqtt-Server publishAll,Topic:{},Obj=\n{},\nMessageFullName={}", topic, json, builder
                .getDescriptorForType().getFullName());
        boolean result = false;
        result = server.publishAll(topic, ProtoBufUtil.deserializationToByteArray(obj, builder), qos);
        log.info("Mqtt-Server publishAll result:{}", result);
        return result;
    }

}